using System;
using System.Collections.Generic;
using System.Text;
using TVDesigner.Entities.Elements;
using TVDesigner.Entities;

namespace TVDesigner.Generator.GeneratorEntities
{
    public class ProjectXletGenerator
    {
        private ProjectXlet _ProjectXlet;

        public ProjectXletGenerator(ProjectXlet projectXlet)
        {
            _ProjectXlet = projectXlet;
        }

        public List<ImageFile> GetImageFiles()
        {
            List<ImageFile> list = new List<ImageFile>();

            foreach (Screen sc in _ProjectXlet.Screens)
            {
                foreach (HButton button in sc.HButtons)
                {
                    if (button.Imagem != null)
                    {
                        ImageFile imagem = new ImageFile(button.Imagem);

                        if (!list.Contains(imagem))
                        {
                            list.Add(imagem);
                        }
                    }
                    if (button.FocusImage != null)
                    {
                        ImageFile imagem = new ImageFile(button.FocusImage);

                        if (!list.Contains(imagem))
                        {
                            list.Add(imagem);
                        }
                    }
                }
                foreach (HIcon icon in sc.HIcons)
                {
                    if (icon.Imagem != null)
                    {
                        ImageFile imagem = new ImageFile(icon.Imagem);

                        if (!list.Contains(imagem))
                        {
                            list.Add(imagem);
                        }
                    }
                }
            }

            return list;
        }

        #region Construindo class Xlet

        public string DeclareClass()
        {
            string package = _ProjectXlet.Name.ToLower();
            StringBuilder sb = new StringBuilder();

            //package
            if (package != null && !package.Equals(string.Empty))
            {
                sb.Append("package ").Append(package).Append(";\n\n");
            }

            //imports.
            sb.Append(@"
import javax.media.Player;
import javax.tv.media.AWTVideoSize;
import javax.tv.media.AWTVideoSizeControl;
import javax.tv.xlet.XletContext;
import javax.tv.service.selection.ServiceContentHandler;
import javax.tv.service.selection.ServiceContextFactory;
import javax.tv.xlet.Xlet;
import javax.tv.xlet.XletStateChangeException;
import org.havi.ui.HContainer;
import org.havi.ui.HScene;
import org.havi.ui.HSceneFactory;
import org.havi.ui.HScreen;
import java.awt.Rectangle;
import java.awt.Color;


");
            //class declaration.
            sb.Append("public class ").Append(_ProjectXlet.NameStartedWithUpperCase).Append(" extends HContainer implements Xlet {\n");
            sb.Append("\n");

            //atributes
            _LoadAtributesDeclaration(sb);
            sb.Append("\n");

            //constructors.
            _LoadConstructor(sb);
            sb.Append("\n");

            //methods.
            _LoadMethods(sb);
            sb.Append("\n");

            sb.Append("}\n");

            return sb.ToString();
        }
        #endregion

        private void _LoadAtributesDeclaration(StringBuilder sb)
        {
            _LoadStaticScreenNumerationAtributes(sb);
            sb.AppendLine("");
            sb.AppendLine("\tprotected HScene scene;");
            sb.AppendLine("\tprotected XletContext context;");
            sb.AppendLine("\tprotected TVDesignerScreen[] screens;");
            sb.AppendLine("\tprotected TVDesignerScreen currentScreen;");
            sb.AppendLine("\tprotected TVDesignerScreen previousScreen;");
            sb.AppendLine("\tprotected TVDesignerKeyListener listener;");
            sb.AppendLine("\tprotected AWTVideoSize awtVideoSize;");

            //TODO - acrescentar os outros atributos.
        }

        private void _LoadStaticScreenNumerationAtributes(StringBuilder sb)
        {
            int count = 0;
            foreach (Screen screen in _ProjectXlet.Screens)
            {
                sb.Append("\tpublic static final int ").Append(screen.Name.ToUpper()).Append(" = ").Append(count++).AppendLine(";");
            }
        }

        private void _LoadConstructor(StringBuilder sb)
        {

        }

        private void _LoadMethods(StringBuilder sb)
        {
            _LoadInitMethod(sb);
            sb.AppendLine();
            _LoadStartXletMethod(sb);
            sb.AppendLine();
            _LoadInitXletMethod(sb);
            sb.AppendLine();
            _LoadDestroyXletMethod(sb);
            sb.AppendLine();
            _LoadPauseXletMethod(sb);
            sb.AppendLine();
            _LoadSetCurrentScreen(sb);
            sb.AppendLine();
            _LoadGetListenerMethod(sb);
            sb.AppendLine();
            _LoadGetCurrentScreenMethod(sb);
            sb.AppendLine();
            _LoadResizeMethod(sb);
        }

        private void _LoadInitMethod(StringBuilder sb)
        {
            sb.Append("\tprotected void init() {\n");

            sb.Append(@"
        this.scene = HSceneFactory.getInstance().getFullScreenScene(
        HScreen.getDefaultHScreen().getDefaultHGraphicsDevice());

        this.scene.setLayout(null);
        this.scene.setLocation(0, 0);

        Rectangle rect = scene.getBounds();
		System.out.println(rect.toString());
        this.setBounds(rect);

        this.setVisible(true);
        this.setBackground(Color.black);

		this.scene.add(this);
        this.scene.setVisible(true);

		this.requestFocus();        
    }
");
        }

        #region Metodos que implementam a interface do Xlet

        private void _LoadStartXletMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic void startXlet() throws XletStateChangeException {");
            sb.AppendLine("\t\tthis.init();");
            sb.AppendLine();

            sb.Append("\t\tthis.screens = new TVDesignerScreen[").Append(_ProjectXlet.Screens.Count).AppendLine("];");
            sb.AppendLine("\t\tthis.listener = new TVDesignerKeyListener(this);");

            int count = 0;
            int startPointIndex = -1;
            foreach (Screen screen in _ProjectXlet.Screens)
            {
                sb.Append("\t\tthis.screens[").Append(count).Append("] = new ").Append(screen.NameStartedWithUpperCase).AppendLine("(this);");
                if (screen.Name.Equals(_ProjectXlet.StartScreen))
                {
                    startPointIndex = count;
                }
                count++;
            }
            sb.AppendLine();

            count = 0;
            foreach (Screen screen in _ProjectXlet.Screens)
            {
                sb.Append("\t\tthis.add(").Append("screens[").Append(count).AppendLine("]);");
                count++;
            }

            sb.AppendLine();

            sb.Append("\t\tthis.setCurrentScreen(this.screens[").Append(startPointIndex).AppendLine("]);");

            sb.AppendLine();
            sb.AppendLine("\t}");
        }

        private void _LoadPauseXletMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic void pauseXlet() {");
            sb.AppendLine("\t\t// TODO Auto-generated method stub");
            sb.AppendLine("\t}");
        }

        private void _LoadDestroyXletMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic void destroyXlet(boolean arg0) throws XletStateChangeException {");
            sb.AppendLine("\t\t// TODO Auto-generated method stub");
            sb.AppendLine("\t}");
        }

        private void _LoadInitXletMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic void initXlet(XletContext arg0) throws XletStateChangeException {");
            sb.AppendLine("\t\tthis.context = arg0;");
            sb.AppendLine("\t}");
        }
        #endregion

        private void _LoadSetCurrentScreen(StringBuilder sb)
        {
            sb.AppendLine("\tpublic void setCurrentScreen(int screen) {");
            sb.AppendLine("\t\tthis.previousScreen = this.currentScreen;");
            sb.AppendLine("\t\tthis.setCurrentScreen(this.screens[screen]);");
            sb.AppendLine("\t}");
            sb.AppendLine("");
            sb.AppendLine("\tpublic void setCurrentScreen(TVDesignerScreen newCurrentScreen) {");
            sb.AppendLine("\t\tif (this.currentScreen != null) {");
            sb.AppendLine("\t\t\tthis.currentScreen.setVisible(false);");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tthis.currentScreen = newCurrentScreen;");
            sb.AppendLine("\t\tthis.currentScreen.setVisible(true);");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            sb.AppendLine("\tpublic TVDesignerScreen getPreviousScreen() {");
            sb.AppendLine("\t\treturn this.previousScreen;");
            sb.AppendLine("\t}");
        }

        private void _LoadGetListenerMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic TVDesignerKeyListener getListener() {");
            sb.AppendLine("\t\treturn this.listener;");
            sb.AppendLine("\t}");
        }

        private void _LoadGetCurrentScreenMethod(StringBuilder sb)
        {
            sb.AppendLine("\tpublic TVDesignerScreen getCurrentScreen() {");
            sb.AppendLine("\t\treturn this.currentScreen;");
            sb.AppendLine("\t}");
        }

        private static void _LoadResizeMethod(StringBuilder sb)
        {
            sb.Append(@"
    /**
	 * Resize the video.
	 * 
	 * @param size - AWTVideoSize (currentSize, finalSize)
	 */
	public void resize(AWTVideoSize size) {		

        if (this.awtVideoSize == null) {
            this.awtVideoSize = size;
        } else if (this.awtVideoSize.equals(size)) {
            return;
        }	 
		ServiceContextFactory serviceContextFactory = null;			
		javax.tv.service.selection.ServiceContext serviceContext = null;
				
		try {
			serviceContextFactory = ServiceContextFactory.getInstance();				
			serviceContext = serviceContextFactory.getServiceContext(context);	
		}
		catch (Exception ex) {				
			ex.printStackTrace();				
		}
				
		if (serviceContext != null) {			
			ServiceContentHandler[] serviceContentHandler = serviceContext.getServiceContentHandlers();
			Player player = null;
			
			if (serviceContentHandler.length > 0) {				
				player = (Player) serviceContentHandler[0];		
			}
 
			if (player != null) {				
				AWTVideoSizeControl awtVideoSizeControl = (AWTVideoSizeControl) player.getControl(").Append("\"javax.tv.media.AWTVideoSizeControl\");\n");
            sb.Append(@"
                awtVideoSizeControl.setSize(size);
			}
		}
	}");
        }




    }        
}
